#include <stdlib.h>
#include <dllLib.h>
/*
   ---------             --------          --------
   | head--------------->| next----------->| next---------
   |       |             |      |          |      |      |
   |       |        ------ prev |<---------- prev |      |
   |       |       |     |      |          |      |      |
   | tail------    |     | ...  |    ----->| ...  |      |
   |-------|  |    v                 |                   v
			  |  -----               |                 -----
			  |   ---                |                  ---
			  |    -                 |                   -
			  ------------------------
EMPTY LIST:
	-----------
		|  head------------------
		|         |             |
		|  tail----------       |
		|         |     v       v
		|         |   -----   -----
		-----------    ---     ---						-       -
*/

STATUS dllInit(DL_LIST* pList)
{
	pList->head = NULL;
	pList->tail = NULL;

	return (OK);
}

void dllInsert(
	DL_LIST* pList, /* pointer to list descriptor */
	DL_NODE* pPrev, /* pointer to node after which to insert */
	DL_NODE* pNode	/* pointer to node to be inserted */
)
{
	DL_NODE* pNext;

	if (pPrev == NULL)
	{
		pNext = pList->head;
		pList->head = pNode;
	}
	else
	{
		pNext = pPrev->next;
		pPrev->next = pNode;
	}

	if (pNext == NULL)
		pList->tail = pNode;
	else
		pNext->previous = pNode;

	pNode->next     = pNext;
	pNode->previous = pPrev;
}

void dllAdd(
	DL_LIST* pList, /* pointer to list descriptor */
	DL_NODE* pNode	/* pointer to node to be added */
)
{
	dllInsert(pList, pList->tail, pNode);
}

void dllRemove(
	DL_LIST* pList, /* pointer to list descriptor */
	DL_NODE* pNode	/* pointer to node to be deleted */
)
{
	if (pNode->previous == NULL)
		pList->head = pNode->next;
	else
		pNode->previous->next = pNode->next;

	if (pNode->next == NULL)
		pList->tail = pNode->previous;
	else
		pNode->next->previous = pNode->previous;
	pNode->next = NULL;
	pNode->previous = NULL;
}

DL_NODE* dllGet(DL_LIST* pList)
{
	DL_NODE* pNode = NULL;

	pNode = DLL_FIRST(pList);

	if (pNode != NULL)
	{
		pList->head = pNode->next;

		if (pNode->next == NULL)
			pList->tail = NULL;
		else
			pNode->next->previous = NULL;
	}

	return (pNode);
}

int dllCount(DL_LIST* pList)
{
	DL_NODE* pNode = NULL;
	int count = 0;

	pNode = DLL_FIRST(pList);
	while (pNode != NULL)
	{
		count++;
		pNode = DLL_NEXT(pNode);
	}

	return (count);
}

DL_NODE* dllEach(DL_LIST* pList, DLL_EACH_FUNC routine, arg_t routineArg)
{
	DL_NODE* pNode = NULL;

	pNode = DLL_FIRST(pList);
	while (pNode != NULL)
	{
		if (((*routine)(pNode, routineArg)) != TRUE)
			break;
		pNode = DLL_NEXT(pNode);
	}
	return (pNode);
}
